package com.hzzftech.watchdog.busi.core.file.repository;

import com.hzzftech.watchdog.busi.constants.BusiConstant;
import com.hzzftech.watchdog.busi.domain.KtDispatcher;
import com.hzzftech.watchdog.busi.domain.KtFileRepositoryMsg;
import com.hzzftech.watchdog.busi.domain.KtJob;
import com.hzzftech.watchdog.busi.domain.KtRepositoryFile;
import com.hzzftech.watchdog.busi.service.IKtDispatcherService;
import com.hzzftech.watchdog.busi.service.IKtJobService;
import com.hzzftech.watchdog.busi.service.IKtRepositoryFileService;
import com.hzzftech.watchdog.busi.utils.FileUtils;
import com.hzzftech.watchdog.common.utils.spring.SpringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.*;

/**
 * GIT资源库解析器
 */
public class KtGitRepositoryFileParser implements FileParser{

    private List<KtRepositoryFile> repList;

    private Long repositoryId;

    private IKtRepositoryFileService fileService;

    private Git git;

    public static Logger logger = LoggerFactory.getLogger(KtGitRepositoryFileParser.class);

    public KtGitRepositoryFileParser(IKtRepositoryFileService fileService, Long repositoryId, Git git) {
        if (Objects.isNull(fileService) || Objects.isNull(repositoryId)) {
            throw new NullPointerException("IKtRepositoryFileService和repositoryId不能为null");
        }
        this.repositoryId = repositoryId;
        repList = new ArrayList<>();
        this.git = git;
        this.fileService = fileService;
    }

    public static class FileWithParent {
        public Long parent;
        public File f;
    }

    @Override
    @Transactional
    public FileParser parse(File fp) {
        List<KtRepositoryFile> existsRFList = fileService.selectKtRepositoryFileByParentId(repositoryId);

        // 广度优先遍历文件夹
        Queue<FileWithParent> fq = new LinkedList<>();

        FileWithParent fwp = new FileWithParent();
        fwp.parent = 0L;
        fwp.f = fp;
        fq.offer(fwp);

        while (!fq.isEmpty()) {
            FileWithParent poll = fq.poll();

            if (poll.f.isFile()) {
                KtRepositoryFile keep = null;
                for (int i = 0;  i < existsRFList.size(); i++) {
                    if (existsRFList.get(i).getParentId().equals(poll.parent) && existsRFList.get(i).getfName().equals(poll.f.getName()) && existsRFList.get(i).getRepositoryId().equals(repositoryId)) {
                        keep = existsRFList.get(i);
                        break;
                    }
                }
                if (Objects.isNull(keep)) {
                    KtRepositoryFile repositoryFile = new KtRepositoryFile(
                            repositoryId,
                            poll.parent,
                            poll.f.getName(),
                            FileUtils.getSuffixName(poll.f.getName()),
                            BusiConstant.FILE_TYPE_F,
                            poll.f.getUsableSpace());
                    repositoryFile.setStatus(BusiConstant.STATUS_YES);
//                    if (git != null) {
//                        RevCommit logs = null;
//                        try {
//                            logs = (RevCommit) git.log().addPath(getFilePath(repositoryFile)).call();
//
//                                System.out.println(logs.getFullMessage().);
//
//                            System.out.println(logs);
//                        } catch (GitAPIException e) {
//                            e.printStackTrace();
//                        }
//                    }
                    fileService.insertKtRepositoryFile(repositoryFile);
                } else {
                    existsRFList.remove(keep);
                }

            } else {
                KtRepositoryFile keep = null;
                for (int i = 0;  i < existsRFList.size(); i++) {
                    if (existsRFList.get(i).getParentId().equals(poll.parent) && existsRFList.get(i).getfName().equals(poll.f.getName()) && existsRFList.get(i).getRepositoryId().equals(repositoryId)) {
                        keep = existsRFList.get(i);
                        break;
                    }
                }

                if (Objects.isNull(keep)) {
                    keep = new KtRepositoryFile(
                            repositoryId,
                            poll.parent,
                            poll.f.getName(),
                            FileUtils.getSuffixName(poll.f.getName()),
                            BusiConstant.FILE_TYPE_DIRECTORY,
                            poll.f.getUsableSpace());
                    keep.setStatus(BusiConstant.STATUS_YES);
//                    if (git != null) {
//                        RevCommit logs = null;
//                        try {
//                            logs = (RevCommit) git.log().addPath(getFilePath(keep)).call();
//
//                            System.out.println(logs);
//                        } catch (GitAPIException e) {
//                            e.printStackTrace();
//                        }
//                    }
                    fileService.insertKtRepositoryFile(keep);
                } else {
                    existsRFList.remove(keep);
                }


                File[] chs = poll.f.listFiles(pathname -> !pathname.getName().startsWith("."));

                for (File f : chs) {
                    FileWithParent fwp1 = new FileWithParent();
                    fwp1.parent = keep.getId();
                    fwp1.f = f;
                    fq.offer(fwp1);
                }
            }
        }

        existsRFList.forEach(e -> {
            IKtDispatcherService dispatcherService = SpringUtils.getBean(IKtDispatcherService.class);
            IKtJobService jobService = SpringUtils.getBean(IKtJobService.class);

            KtDispatcher dispatcher = new KtDispatcher();
            dispatcher.setDpId(e.getId());
            dispatcher.setDpRepoType(BusiConstant.REPOSITORY_TYPE_GIT);
            List<KtDispatcher> list = dispatcherService.selectKtDispatcherList(dispatcher);
            for (KtDispatcher item :list ) {
                KtJob job = new KtJob();
                job.setDpId(item.getId());
                List<KtJob> ktJobs = jobService.selectJobList(job);
                try {
                    for (KtJob job1 : ktJobs) {
                        jobService.deleteJob(job1);
                    }
                } catch (Exception e2) {
                    throw new RuntimeException(e2);
                }
                dispatcherService.deleteKtDispatcherById(item.getId());
            }
            fileService.deleteKtRepositoryFileById(e.getId());
        });

        return this;
    }

    public KtRepositoryFile getRespByName(String name) {
        return fileService.selectKtRepositoryByName(name);
    }


    public KtRepositoryFile getUniqueResp(Long repositoryId, Long parentId, String fName, List<KtRepositoryFile> list) {
        KtRepositoryFile find = null;

        if (Objects.isNull(repositoryId) || Objects.isNull(parentId) || Objects.isNull(fName) || list==null ) {
            throw new NullPointerException();
        }

        for (KtRepositoryFile e : list) {
            if (e.getParentId().equals(parentId) && e.getfName().equals(fName) && e.getRepositoryId().equals(repositoryId)){
                find = e;
                break;
            }
        }

        return find;
    }


    @Override
    public List<KtRepositoryFile> getResultList() {
        return getRepList();
    }

    public String getFilePath(KtRepositoryFile file){
        StringBuilder res = new StringBuilder(File.separator+file.getfName());
        KtRepositoryFile work = file;

        while (!work.getParentId().equals(0L)) {
            KtRepositoryFile parentFile = fileService.selectKtRepositoryFileById(work.getParentId());
            res.insert(0,File.separator+ parentFile.getfName());
            work = parentFile;
        }
        return res.toString();
    }

    public List<KtRepositoryFile> getRepList() {
        return repList;
    }

    public void setRepList(List<KtRepositoryFile> repList) {
        this.repList = repList;
    }

    public Long getRepositoryId() {
        return repositoryId;
    }

    public void setRepositoryId(Long repositoryId) {
        this.repositoryId = repositoryId;
    }
}
